<template>
  <div>
    <h1>watch</h1>
    <h2>{{ count }}</h2>
    <h2>{{ obj }}</h2>
    <h2>{{ obj2 }}</h2>
    <button @click="stop">测试停止监听</button>
  </div>
</template>

<script setup>
import { reactive, ref, watch, watchEffect } from 'vue';

/**
 * 监听一个响应式数据
 *  ref对象
 *  reactive响应式对象
 * 语法 watch函数 第一个参数 监听的源 第二个参数 回调函数
 *    回调函数里有2个参数，第一个参数是新 第二个是旧（这个相对用的少）
 * 
 * 
 * 监听多个响应式数据
 * 语法 watch函数 第一个是数组，里面可以写多个源（响应式数据），第二个参数 回调函数
 *    回调函数里还是2个参数 第一个参数新值 也是个数组 第二个参数 旧值 也是个数组
 * 
 * 
 * 监听一个对象中的属性 简单数据
 *  watch{
 *  'obj.age': xxx
 *  }
 *  语法 watch(() => 属性， 回调函数)
 *  第一个参数是个回调函数 返回值就是监听哪个属性
 *  第二个 回调函数 和之前一样
 * 
 * 监听一个对象中的属性 复杂数据
 *  语法 watch(() => 属性 , 回调函数) 
 * 第一个参数是个回调函数 返回值就是监听哪个属性
 *  第二个 回调函数 和之前一样
 *  第三个参数 对象
 *    对象中 有2个常用属性 immediate(立即执行) deep(深度监听)
 *     - 不同的地方 要配置deep: true
 */
const count = ref(0)
const obj = reactive({ name: 'zs', age: 18, hobby: [{ id: 1, desc: '吃饭' }, { id: 2, desc: '睡觉' }] })

const obj2 = ref({ name: 'zs', age: 18, hobby: [{ id: 1, desc: '吃饭' }, { id: 2, desc: '睡觉' }] })
// setTimeout(() => {
//   count.value++
// }, 2000)
setTimeout(() => {
  obj.age++
}, 3000)
// setTimeout(() => {
//   obj.hobby[0].desc = '打豆豆'
// }, 2000)
// setTimeout(() => { 
//   obj2.value.hobby[0].desc = '1234'
//  }, 2000)

// setInterval(() => {
//   count.value++
// }, 1000);

// 监听一个源
// const stop = watch(count, newCount => {
//   console.log('监听count变了他的值是', newCount);
// })
// watch(obj, val => {
//   console.log('监听对象中的年龄改变了', val);
// })

// 监听多个源 - 只要有其中一个源改变了，那们就会触发回调函数
// watch([count, () => obj.age], ([newCount, newAge], [oldCount, oldAge]) => {
//   if (newCount !== oldCount) {
//     console.log('count改变了', newCount);
//   }
//   // 后续讲一个解决方式，监听对象中某个属性改变
//   // console.log(newAge, oldAge);
//   if (newAge !== oldAge) {
//     console.log('obj改变了', newAge);
//   }
// })

/**
 * 监听单个属性 简单数据
 * 
 * 先错误示范
 * 这个写法监听单个属性语法是错误的
 * 你这么写相当于就是
 * watch(18, val => {
 * })
 * 
 * 以下代码是正确的代码
 */
// watch(() => obj.age, val => {
//   console.log('age改变了', val);
// })

// 监听单个属性 复杂数据
// watch(() => obj.hobby, val => {
//   console.log('hobby改变了', val);
// }, {
//   immediate: true, // 立即执行
//   deep: true // 深度监听
// })

// watch(obj, (val) => {
//   console.log(val);
// })

// watch(obj2, val => {
//   console.log(val);
// }, {
//   deep: true
// })

/**
 * 立即执行
 * 第一个参数回调函数
 * 函数中 只要处理了响应式数据的字段
 * 字段改变了，这个函数就会触发
 *  - 注意ref对象要写成count.value
 *  - 想监听对象中的属性，要写点属性才能监听到
 * 
 * 
 * 与 watchEffect() 相比，watch() 使我们可以：

  懒执行副作用；watch默认不会执行
  更加明确是应该由哪个状态触发侦听器重新执行； watch是要配置监听源的
  可以访问所侦听状态的前一个值和当前值。watch是可以拿到新值和旧值

  watchEffect书写简单，只要你想监听的东西都写在里面，一变化就会触发回调
  vue3小兔鲜 会用到watchEffect
  医疗项目 用的watch
 */
watchEffect(() => {
  // console.log(count.value);
  // console.log(obj.age);
})


</script>

<style lang="scss" scoped></style>